package com.ruoyi.datastatistics.service.impl;

import cn.hutool.core.date.DatePattern;
import cn.hutool.core.date.DateUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.ruoyi.alarmmanagement.domain.DmWarn;
import com.ruoyi.alarmmanagement.mapper.DmWarnMapper;
import com.ruoyi.basedata.domain.ElectricityAreaReport;
import com.ruoyi.basedata.domain.ElectricityTerminalsXb;
import com.ruoyi.basedata.domain.MeterSheets;
import com.ruoyi.basedata.domain.TerminalsXb;
import com.ruoyi.basedata.mapper.ElectricityAreaReportMapper;
import com.ruoyi.basedata.mapper.ElectricityTerminalsXbMapper;
import com.ruoyi.basedata.mapper.MeterSheetsMapper;
import com.ruoyi.basedata.mapper.TerminalsXbMapper;
import com.ruoyi.basedata.service.IMeterSheetsService;
import com.ruoyi.common.core.domain.entity.SysDictData;
import com.ruoyi.datastatistics.domain.ElectricityTerminalsFreezeXb;
import com.ruoyi.datastatistics.domain.TerminalsFreezeXb;
import com.ruoyi.datastatistics.domain.vo.EnergyUseRankVo;
import com.ruoyi.datastatistics.mapper.BillMapper;
import com.ruoyi.datastatistics.mapper.ElectricityTerminalsFreezeXbMapper;
import com.ruoyi.datastatistics.mapper.TerminalsFreezeXbMapper;
import com.ruoyi.datastatistics.service.IBigScreenService;
import com.ruoyi.system.mapper.SysDictDataMapper;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.*;
import java.util.stream.Collectors;

/**
* @Description: 能耗监控平台
* @date: 2025/6/6 09:01
* @author: zt
*/
@Service
public class BigScreenServiceImpl implements IBigScreenService {


    @Resource
    private ElectricityTerminalsFreezeXbMapper electricityTerminalsFreezeXbMapper;

    @Resource
    private TerminalsFreezeXbMapper terminalsFreezeXbMapper;

    @Resource
    private BillMapper billMapper;

    @Resource
    private ElectricityTerminalsXbMapper electricityTerminalsXbMapper;

    @Resource
    private TerminalsXbMapper terminalsXbMapper;

    @Resource
    private DmWarnMapper dmWarnMapper;

    @Resource
    private ElectricityAreaReportMapper electricityAreaReportMapper;

    @Resource
    private SysDictDataMapper sysDictDataMapper;

    @Resource
    private IMeterSheetsService meterSheetsService;

    private static final String FROZEN_TYPE_DAY = "day";
    private static final String FROZEN_TYPE_MONTH = "month";

    private static final String[] ENERGY_USE_ITEM_ARR = new String[]{"","energy_use_item","energy_use_item_water","",""};

    /**
     * @Description: 年度能源（电，水，气，热）累计用量汇总
     * @date: 2025/6/6 09:46
     * @author: zt
     */
    @Override
    public Map<String, Object> getEnergyYearData(String tenantId) {
        //今年1月1号
        String startDay = DateUtil.formatDate(DateUtil.beginOfYear(new Date()));
        //今天
        String endDay = DateUtil.formatDate(new Date());
        //查找今年的所有能源类型的累计用量
        Map<String, Object> resMap = new HashMap<>();
        resMap.put("elec","0");
        resMap.put("water","0");
        resMap.put("air","0");
        resMap.put("heat","0");
        //电
        List<ElectricityTerminalsFreezeXb> elecList = electricityTerminalsFreezeXbMapper.selectList(new LambdaQueryWrapper<ElectricityTerminalsFreezeXb>()
                .eq(ElectricityTerminalsFreezeXb::getTenantId,tenantId).eq(ElectricityTerminalsFreezeXb::getFrozenType,FROZEN_TYPE_DAY)
                .ge(ElectricityTerminalsFreezeXb::getFreezeTime,startDay).le(ElectricityTerminalsFreezeXb::getFreezeTime,endDay));
        Double elecValue = elecList.stream().mapToDouble(item -> item.getDosageCombinationActiveEnergy1() == null ? 0d : item.getDosageCombinationActiveEnergy1().doubleValue()).sum();
        resMap.put("elec",elecValue);
        //水
        List<TerminalsFreezeXb> waterList = terminalsFreezeXbMapper.selectList(new LambdaQueryWrapper<TerminalsFreezeXb>()
                .eq(TerminalsFreezeXb::getTenantId,tenantId).eq(TerminalsFreezeXb::getFrozenType,FROZEN_TYPE_DAY)
                .ge(TerminalsFreezeXb::getFreezeTime,startDay).le(TerminalsFreezeXb::getFreezeTime,endDay));
        Double waterValue = waterList.stream().mapToDouble(item -> item.getCumulativeFlow() == null ? 0d : item.getCumulativeFlow().doubleValue()).sum();
        resMap.put("water",waterValue);
        //气
        //todo
        //热
        //todo
        return resMap;
    }

    /**
     * @Description: 上月与上上月各类能源的费用情况
     * @date: 2025/6/6 09:46
     * @author: zt
     */
    @Override
    public Map<String, Object> getEnergyCostData(String tenantId) {
        Map<String, Object> resMap = new HashMap<>();
        Date now = DateUtil.date();
        //上月
        String month1 = DateUtil.format(DateUtil.offsetMonth(now,-1), DatePattern.NORM_MONTH_FORMAT);
        //上上月
        String month2 = DateUtil.format(DateUtil.offsetMonth(now,-2), DatePattern.NORM_MONTH_FORMAT);
        String[] monthList = new String[]{month2,month1};
        String[] yAxisArr = new String[]{"热","气","水","电"};
        resMap.put("yAxisData",yAxisArr);
        //系列数组
        List<Map<String,Object>> seriesList = new ArrayList<>();
        //循环2次，两个月份数据
        for (String month : monthList) {
            List<Double> doubleList = new ArrayList<>();
            Map<String,Object> tempMap = new HashMap<>();
            tempMap.put("name",month.replace("-",""));
            tempMap.put("type","bar");
            //热
            //todo
            doubleList.add(0d);
            //气
            //todo
            doubleList.add(0d);
            //水
            Double water =  billMapper.selectTotalPriceInMonth(tenantId,month,2);
            doubleList.add(water);
            //电
            Double elec =  billMapper.selectTotalPriceInMonth(tenantId,month,1);
            doubleList.add(elec);
            tempMap.put("data",doubleList);

            seriesList.add(tempMap);
        }
        resMap.put("series",seriesList);
        return resMap;
    }

    /**
     * @Description: 各类能源类型的采集设备统计
     * @date: 2025/6/6 09:46
     * @author: zt
     */
    @Override
    public Map<String, Object> getEnergyDeviceCountData(String tenantId) {
        Map<String, Object> resMap = new HashMap<>();
        resMap.put("elec","0");
        resMap.put("water","0");
        resMap.put("air","0");
        resMap.put("heat","0");
        //电
        Integer elecCount = electricityTerminalsXbMapper.selectList(new LambdaQueryWrapper<ElectricityTerminalsXb>().eq(ElectricityTerminalsXb::getTenantId,tenantId)
                .eq(ElectricityTerminalsXb::getDelFlag,0)).size();
        resMap.put("elec",elecCount);
        //水
        Integer waterCount = terminalsXbMapper.selectList(new LambdaQueryWrapper<TerminalsXb>().eq(TerminalsXb::getTenantId,tenantId)
                .eq(TerminalsXb::getDelFlag,0)).size();
        resMap.put("water",waterCount);
        //气
        //todo
        //热
        //todo
        return resMap;
    }

    /**
     * @Description: 租户用量排名
     * @date: 2025/6/6 09:46
     * @author: zt
     */
    @Override
    public List<EnergyUseRankVo> getEnergyUseRankData(String tenantId, Integer energyType) {
        List<EnergyUseRankVo> resList = new ArrayList<>();
        Date now = DateUtil.date();
        //上月
        String month1 = DateUtil.format(DateUtil.offsetMonth(now,-1), DatePattern.NORM_MONTH_FORMAT);
        //上上月
        String month2 = DateUtil.format(DateUtil.offsetMonth(now,-2), DatePattern.NORM_MONTH_FORMAT);

        if(energyType == 1){
            //电
            resList = electricityTerminalsFreezeXbMapper.selectUseRank(tenantId, month1, month2);
        }else if(energyType == 2){
            //水
            resList = terminalsFreezeXbMapper.selectUseRank(tenantId,month1);
        }else if(energyType == 3){
            //气
            //todo
        }else if(energyType == 4){
            //热
            //todo
        }
        return resList;
    }

    /**
     * @Description: 各能源年用量统计
     * @date: 2025/6/6 09:46
     * @author: zt
     */
    @Override
    public Map<String, Object> getEnergyYearUseData(String tenantId) {

        Map<String, Object> resMap = new HashMap<>();
        Date now = DateUtil.date();
        //今年1月1号
        String startDay = DateUtil.formatDate(DateUtil.beginOfYear(now));
        //今年最后一天
        String endDay = DateUtil.formatDate(DateUtil.endOfYear(now));
        Integer year = DateUtil.year(now);
        String[] monthList = new String[]{"01","02","03","04","05","06","07","08","09","10","11","12"};
        resMap.put("xAxisData",monthList);

        //电年数据
        List<ElectricityTerminalsFreezeXb> elecFreezeList = electricityTerminalsFreezeXbMapper.selectList(new LambdaQueryWrapper<ElectricityTerminalsFreezeXb>()
                .eq(ElectricityTerminalsFreezeXb::getTenantId,tenantId).eq(ElectricityTerminalsFreezeXb::getFrozenType,FROZEN_TYPE_DAY)
                .ge(ElectricityTerminalsFreezeXb::getFreezeTime,startDay).le(ElectricityTerminalsFreezeXb::getFreezeTime,endDay));
        Map<String,List<ElectricityTerminalsFreezeXb>> elecMonthMap = elecFreezeList.stream().collect(Collectors.groupingBy(item->item.getFreezeTime().substring(0,7)));
        //水年数据
        List<TerminalsFreezeXb> waterFreezeList = terminalsFreezeXbMapper.selectList(new LambdaQueryWrapper<TerminalsFreezeXb>()
                .eq(TerminalsFreezeXb::getTenantId,tenantId).eq(TerminalsFreezeXb::getFrozenType,FROZEN_TYPE_DAY)
                .ge(TerminalsFreezeXb::getFreezeTime,startDay).le(TerminalsFreezeXb::getFreezeTime,endDay));
        Map<String,List<TerminalsFreezeXb>> waterMonthMap = waterFreezeList.stream().collect(Collectors.groupingBy(item->item.getFreezeTime().substring(0,7)));
        //气年数据
        //todo
        //热年数据
        //todo

        //系列数组
        List<Map<String,Object>> seriesList = new ArrayList<>();
        String[] labels = new String[]{"电","水","气","热"};
        for (String label : labels) {
            List<Double> doubleList = new ArrayList<>();
            //循环12次
            for (String month : monthList) {
                String key = year + "-" + month;
                if("电".equals(label)){
                    List<ElectricityTerminalsFreezeXb> tempList = elecMonthMap.get(key);
                    Double elecValue = tempList == null ? 0d : tempList.stream().mapToDouble(item -> item.getDosageCombinationActiveEnergy1() == null ? 0d : item.getDosageCombinationActiveEnergy1().doubleValue()).sum();
                    doubleList.add(elecValue);
                }else if("水".equals(label)){
                    List<TerminalsFreezeXb> tempList = waterMonthMap.get(key);
                    Double waterValue = tempList == null ? 0d : tempList.stream().mapToDouble(item -> item.getCumulativeFlow() == null ? 0d : item.getCumulativeFlow().doubleValue()).sum();
                    doubleList.add(waterValue);
                } else {
                    doubleList.add(0d);
                }
            }
            seriesList.add(getSeriesMap(label,doubleList));
        }
        resMap.put("series",seriesList);
        return resMap;

    }

    public Map<String,Object> getSeriesMap(String name,List<Double> valueData) {
        Map<String,Object> tempMap = new HashMap<>();
        tempMap.put("name",name);
        tempMap.put("type","bar");
        tempMap.put("data",valueData);
        return tempMap;
    }

    /**
     * @Description: 各能源分项统计-上个月
     * @date: 2025/6/6 09:46
     * @author: zt
     */
    @Override
    public List<Map<String, Object>> getEnergyItemData(String tenantId,Integer energyType) {
        List<Map<String, Object>> resList = new ArrayList<>();
        Date now = DateUtil.date();
        //上月
        String lastMonth = DateUtil.format(DateUtil.offsetMonth(now,-1), DatePattern.NORM_MONTH_FORMAT);
        //暂时查询电和水
        if(energyType == 1 || energyType == 2){
            //查找分项信息
            List<SysDictData> dictDataList = sysDictDataMapper.selectDictDataByType(ENERGY_USE_ITEM_ARR[energyType]);
            //查找指定能源数据
            List<ElectricityAreaReport> dataList = electricityAreaReportMapper.selectList(new LambdaQueryWrapper<ElectricityAreaReport>().eq(ElectricityAreaReport::getTenantId,tenantId)
                    .eq(ElectricityAreaReport::getFrozenType,FROZEN_TYPE_MONTH).eq(ElectricityAreaReport::getFreezeTime,lastMonth).eq(ElectricityAreaReport::getEnergyUseClassification,energyType));
            Map<String,List<ElectricityAreaReport>> useItemMap = dataList.stream().collect(Collectors.groupingBy(ElectricityAreaReport::getEnergyUseItem));
            for (SysDictData dictData : dictDataList) {
                String key = dictData.getDictValue();
                Map<String,Object> tempMap = new HashMap<>();
                tempMap.put("name",dictData.getDictLabel());
                if(useItemMap.containsKey(key)){
                    Double value = useItemMap.get(key).stream().mapToDouble(item -> item.getCumulativeFlow() == null ? 0d : item.getCumulativeFlow().doubleValue()).sum();
                    tempMap.put("value",value);
                }else {
                    tempMap.put("value",0);
                }
                resList.add(tempMap);
            }
        }
        return resList;
    }

    /**
     * @Description: 报警信息-近7天
     * @date: 2025/6/6 09:46
     * @author: zt
     */
    @Override
    public List<DmWarn> getEnergyWarnData(String tenantId) {
        List<DmWarn> resList = new ArrayList<>();
        //近七天报警
        Date now = DateUtil.date();
        String beginStartTime = DateUtil.formatDateTime(DateUtil.offsetDay(now,-7));
        String endStartTime = DateUtil.formatDateTime(now);
        //传参
        DmWarn warn = new DmWarn();
        warn.setTenantId(tenantId);
        warn.setBeginStartTime(beginStartTime);
        warn.setEndStartTime(endStartTime);
        //电
        List<DmWarn> list1 = dmWarnMapper.selectWarnInBigScreen1(warn);
        //水
        List<DmWarn> list2 = dmWarnMapper.selectWarnInBigScreen2(warn);
        resList.addAll(list1);
        resList.addAll(list2);
        return resList;
    }

    @Override
    public List<Map<String, Object>> getAreaPointInMap(String tenantId, Integer energyType) {
        List<Map<String, Object>> resList = new ArrayList<>();
        Date now = new Date();
        //今年1月1号
        String startDay = DateUtil.formatDate(DateUtil.beginOfYear(now));
        //今天
        String endDay = DateUtil.formatDate(now);
        //上月
        String month1 = DateUtil.format(DateUtil.offsetMonth(now,-1), DatePattern.NORM_MONTH_FORMAT);
        Date startMonth1 = DateUtil.parseDate(month1+"-01");
        Date endMonth1 = DateUtil.endOfMonth(startMonth1);
        //上上月
        String month2 = DateUtil.format(DateUtil.offsetMonth(now,-2), DatePattern.NORM_MONTH_FORMAT);
        Date startMonth2 = DateUtil.parseDate(month2+"-01");
        Date endMonth2 = DateUtil.endOfMonth(startMonth2);
        //如果上上月的开始时间和当前时间不在同一年，则startDay取上上月作为开始时间
        if(DateUtil.year(startMonth2) != DateUtil.year(now)) {
            startDay = DateUtil.formatDate(startMonth2);
        }
        //区域
        List<MeterSheets> sheetsList = meterSheetsService.getAreaTree(1,null,null,null,null,false);
        //最下级
        List<MeterSheets> lastList = recursiveLast(sheetsList);
        List<Long> areaIds = lastList.stream().map(MeterSheets::getId).collect(Collectors.toList());

        //今年以来日数据
        Map<String,List<ElectricityTerminalsFreezeXb>> areaFreezeMap1 = new HashMap<>();
        Map<String,List<TerminalsFreezeXb>> areaFreezeMap2 = new HashMap<>();
        if(energyType == 1){
            //电
            List<ElectricityTerminalsFreezeXb> yearList1 = electricityTerminalsFreezeXbMapper.getFreezeDayInBigScreen1(tenantId,startDay,endDay,areaIds);
            areaFreezeMap1 = yearList1.stream().collect(Collectors.groupingBy(ElectricityTerminalsFreezeXb::getAreaId));
        } else if (energyType == 2) {
            //水
            List<TerminalsFreezeXb> yearList2 = electricityTerminalsFreezeXbMapper.getFreezeDayInBigScreen2(tenantId,startDay,endDay,areaIds);
            areaFreezeMap2 = yearList2.stream().collect(Collectors.groupingBy(TerminalsFreezeXb::getAreaId));
        } else if (energyType == 3) {
            //气
        } else if (energyType == 4) {
            //热
        }
        //整理地图上点位
        for(MeterSheets sheet : lastList){
            String areaId = String.valueOf(sheet.getId());
            //如果没有经纬度就直接进入下个循环
            if(sheet.getLng() == null || sheet.getLat() == null || sheet.getLng().isEmpty() || sheet.getLat().isEmpty()){ continue; }
            Map<String,Object> tempMap = new HashMap<>();
            tempMap.put("info",sheet.getSheetsName());
            tempMap.put("lng",sheet.getLng());
            tempMap.put("lat",sheet.getLat());
            tempMap.put("yearUse",0);
            tempMap.put("monthUse",0);
            tempMap.put("tb",0);
            tempMap.put("hb",0);
            //查询区域用量数据
            if(energyType == 1){
                //电
                if(areaFreezeMap1.containsKey(areaId)){
                    List<ElectricityTerminalsFreezeXb> tempList = areaFreezeMap1.get(areaId);
                    //今年累计用量
                    tempMap.put("yearUse",getUsageWithDiffrentDate1(tempList,DateUtil.beginOfYear(now),now));
                    //本月用量
                    tempMap.put("monthUse",getUsageWithDiffrentDate1(tempList,DateUtil.parseDate(endDay.substring(0,7)+"-01"),now));
                    //上月环比
                    Double monthV1 = getUsageWithDiffrentDate1(tempList,startMonth1,endMonth1);
                    Double monthV2 = getUsageWithDiffrentDate1(tempList,startMonth2,endMonth2);
                    if(monthV2 == 0){
                        tempMap.put("hb",0);
                    } else if (monthV1 == 0) {
                        tempMap.put("hb",100);
                    } else {
                        BigDecimal bd1 = new BigDecimal(monthV1);
                        BigDecimal bd2 = BigDecimal.valueOf((monthV2 - monthV1) * 100);
                        BigDecimal result = bd2.divide(bd1, 2, RoundingMode.HALF_UP);
                        tempMap.put("hb",result.doubleValue());
                    }
                }
            } else if (energyType == 2) {
                //水
                if(areaFreezeMap2.containsKey(areaId)){
                    List<TerminalsFreezeXb> tempList = areaFreezeMap2.get(areaId);
                    //今年累计用量
                    tempMap.put("yearUse",getUsageWithDiffrentDate2(tempList,DateUtil.beginOfYear(now),now));
                    //本月用量
                    tempMap.put("monthUse",getUsageWithDiffrentDate2(tempList,DateUtil.parseDate(endDay.substring(0,7)+"-01"),now));
                    //上月环比
                    Double monthV1 = getUsageWithDiffrentDate2(tempList,startMonth1,endMonth1);
                    Double monthV2 = getUsageWithDiffrentDate2(tempList,startMonth2,endMonth2);
                    if(monthV2 == 0){
                        tempMap.put("hb",0);
                    } else if (monthV1 == 0) {
                        tempMap.put("hb",100);
                    } else {
                        BigDecimal bd1 = new BigDecimal(monthV1);
                        BigDecimal bd2 = BigDecimal.valueOf((monthV2 - monthV1) * 100);
                        BigDecimal result = bd2.divide(bd1, 2, RoundingMode.HALF_UP);
                        tempMap.put("hb",result.doubleValue());
                    }
                }
            } else if (energyType == 3) {
                //气
            } else if (energyType == 4) {
                //热
            }
            resList.add(tempMap);
        }
        return resList;
    }

    private Double getUsageWithDiffrentDate1(List<ElectricityTerminalsFreezeXb> tempList,Date date1,Date date2){
        List<ElectricityTerminalsFreezeXb> list = tempList.stream().filter(item->
                DateUtil.compare(DateUtil.parseDate(item.getFreezeTime()),date1)>=0
                        && DateUtil.compare(DateUtil.parseDate(item.getFreezeTime()),date2)<=0 ).collect(Collectors.toList());
        return list.stream().mapToDouble(item -> item.getDosageCombinationActiveEnergy1() == null ? 0d : item.getDosageCombinationActiveEnergy1().doubleValue()).sum();
    }
    private Double getUsageWithDiffrentDate2(List<TerminalsFreezeXb> tempList,Date date1,Date date2){
        List<TerminalsFreezeXb> list = tempList.stream().filter(item->
                DateUtil.compare(DateUtil.parseDate(item.getFreezeTime()),date1)>=0
                        && DateUtil.compare(DateUtil.parseDate(item.getFreezeTime()),date2)<=0 ).collect(Collectors.toList());
        return list.stream().mapToDouble(item -> item.getCumulativeFlow() == null ? 0d : item.getCumulativeFlow().doubleValue()).sum();
    }

    /**
     * @Description: 返回最下级区域
     * @date: 2025/3/14 13:23
     * @author: zt
     */
    public List<MeterSheets> recursiveLast(List<MeterSheets> sheetsList){
        List<MeterSheets> lastList = new ArrayList<>();
        for (MeterSheets sheet : sheetsList) {
            if (sheet.getChildren() != null && !sheet.getChildren().isEmpty()) {
                lastList.addAll(recursiveLast(sheet.getChildren()));
            } else {
                lastList.add(sheet);
            }
        }
        return lastList;
    }
}
